﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;

namespace Ccit.Utils
{
    /// <summary>
    /// 反射类
    /// </summary>
    public class Reflector
    {
        private ScriptLanguageType m_scriptLanguageType;
		private ScriptExpressionType m_scriptExpressionType;
		private ImportComponentType m_importComponentType;
        private InstanceType m_instanceType;  //反射方法类型(静态方法、实例方法)
		private string m_sImportComponentName;
		private string m_sClassName;
		private string m_sFunctionName;
		private string m_sParameters;
		private object[] m_sParameterArray;  //调用方法时传入的参数
		private ParameterType m_sParameterType;
		private string m_sExcuteExpression;
		private string m_sExcuteScriptCode;
        private object[] m_constructorParam;  //创建实例对象时传入的构造函数的参数

		/// <summary>
		///	获取或设置脚本语言的种类,根据ScriptLanguageType枚举值确定是C#语言还是VB.NET语言
		/// </summary>
		public ScriptLanguageType ScriptLanguageType
		{
			get {return this.m_scriptLanguageType;}
			set {this.m_scriptLanguageType = value;}
		}

		/// <summary>
		///	获取或设置编译表达式的种类,根据ScriptExpressionType确定是计算表达式还是程序代码
		/// </summary>
		public ScriptExpressionType ScriptExpressionType
		{
			get {return this.m_scriptExpressionType;}
			set {this.m_scriptExpressionType = value;}
		}

		/// <summary>
		///	获取或设置导入组件的类型,根据ImportComponentType枚举值选择
		/// </summary>
		public ImportComponentType ImportComponentType
		{
			get {return this.m_importComponentType;}
			set {this.m_importComponentType = value;}
		}

        /// <summary>
        ///  获取或设置反射方法类型(静态方法、实例方法)
        ///  TIM 2008-4-10
        /// </summary>
        public InstanceType InstanceType
        {
            get { return m_instanceType; }
            set{ m_instanceType = value;}
        }

        /// <summary>
        /// 获取或设置 反射调用实例方法时需要传入给构造函数的参数
        /// TIM 2008-4-10
        /// </summary>
        public object[] ConstructorParams
        {
            get { return m_constructorParam; }
            set { m_constructorParam = value;}
        }

        /// <summary>
        /// 参数类型
        /// </summary>
		public ParameterType ParameterType
		{
			get {return this.m_sParameterType;}
			set {this.m_sParameterType = value;}
		}

		/// <summary>
		///	获取或设置需要从外部载入Assembly的组件名称
		/// </summary>
		public string ImportComponentName
		{
			get {return this.m_sImportComponentName;}
			set {this.m_sImportComponentName = value;}
		}

		/// <summary>
		///	获取或设置需要创建的类名
		/// </summary>
		public string ClassName
		{
			get {return this.m_sClassName;}
			set {this.m_sClassName = value;}
		}

		/// <summary>
		///	获取或设置类对象需要调用的方法名称
		/// </summary>
		public string FunctionName
		{
			get {return this.m_sFunctionName;}
			set {this.m_sFunctionName = value;}
		}

		/// <summary>
		///	获取或设置类对象需要调用的方法的参数
		/// </summary>
		public string Parameters
		{
			get {return this.m_sParameters;}
			set {this.m_sParameters = value;}
		}

        /// <summary>
        /// 参数集合
        /// </summary>
		public object[] ParameterArray
		{
			get {return this.m_sParameterArray;}
			set {this.m_sParameterArray = value;}
		}

		/// <summary>
		///	获取或设置需要执行的表达式
		/// </summary>
		public string ExcuteExpression
		{
			get {return this.m_sExcuteExpression;}
			set {this.m_sExcuteExpression = value;}
		}

		/// <summary>
		///	获取待执行代码表达式
		/// </summary>
		public string ExcuteScriptCode
		{
			get {return this.m_sExcuteScriptCode;}
		}

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="componentName">组件名称</param>
        /// <param name="className">类名称</param>
        /// <param name="methodName">方法名称</param>
        /// <param name="methodParams">方法参数</param>
        /// <param name="componentType">组件类型枚举</param>
        /// <param name="instancetype">方法类型枚举</param>
        /// <param name="constructorParams">构造函数参数集合</param>
		public Reflector(string componentName,
                         string className,
                         string methodName, 
                         string methodParams,
                         ImportComponentType componentType,
                         InstanceType instancetype,
                         object[] constructorParams)
		{
			//
			// TODO: 在此处添加构造函数逻辑
			//
			m_scriptLanguageType = ScriptLanguageType.CSharpCode;		//系统默认使用C#语言
			m_scriptExpressionType = ScriptExpressionType.ScriptCode;	//系统默认编译代码;			
			m_importComponentType = ImportComponentType.ComPlusDll;		//系统默认组件类型为COM+组件
			m_sParameterType = ParameterType.Text;						//系统默认参数类型为Text型

            m_instanceType = instancetype;

			this.m_sImportComponentName = componentName;
			this.m_sClassName = className;
			this.m_sFunctionName = methodName;
			this.m_sParameterArray = new string[1]{methodParams};
			this.m_importComponentType = componentType;
            this.m_constructorParam = constructorParams;
		}

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="componentName">组件名称</param>
        /// <param name="className">类名称</param>
        /// <param name="methodName">方法名称</param>
        /// <param name="methodParams">方法参数集合</param>
        /// <param name="componentType">组件类型枚举</param>
        /// <param name="instancetype">方法类型枚举</param>
        /// <param name="constructorParams">构造函数参数集合</param>
		public Reflector(string componentName, 
                         string className, 
                         string methodName, 
                         object[] methodParams, 
                         ImportComponentType componentType,
                         InstanceType instancetype,
                         object[] constructorParams)
		{
			//
			// TODO: 在此处添加构造函数逻辑
			//
			m_scriptLanguageType = ScriptLanguageType.CSharpCode;		//系统默认使用C#语言
			m_scriptExpressionType = ScriptExpressionType.ScriptCode;	//系统默认编译代码;			
			m_importComponentType = ImportComponentType.ComPlusDll;		//系统默认组件类型为COM+组件
			m_sParameterType = ParameterType.Array;						//系统默认参数类型为Text型

		    m_instanceType = instancetype;

			this.m_sImportComponentName = componentName;
			this.m_sClassName = className;
			this.m_sFunctionName = methodName;
			this.m_sParameterArray = methodParams;
			this.m_importComponentType = componentType;
		    this.m_constructorParam = constructorParams;
		}

        /// <summary>
        /// 反射执行
        /// </summary>
        /// <returns></returns>
		public object InvokeMethod()
		{
			object objReturn = null;
			Assembly assembly;
            string sBinFolderPath = getBinFolderPath();
			try
			{
                assembly = Assembly.LoadFrom(sBinFolderPath + this.ImportComponentName);
			}
			catch
			{
				return null;
			}

			string sInstanceName = (this.m_importComponentType == ImportComponentType.ComPlusDll) ? 
				this.ClassName + "Class" : this.ClassName;

			int iCount = assembly.GetTypes().Length;
			for (int i = 0; i < iCount; i++)
			{
				System.Type type = assembly.GetTypes()[i];
				string sInstanceType = sInstanceName.Substring(sInstanceName.LastIndexOf(".") + 1);
				
				if (type.Name == sInstanceType)
				{
					BindingFlags flags = BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public|BindingFlags.Static;

                    object loadedObject;
                    if (m_instanceType == InstanceType.INSTANCE && null != m_constructorParam)
                    {
                        loadedObject = assembly.CreateInstance(sInstanceName, true, BindingFlags.Default, null, m_constructorParam, null, null);
                    }

                    else
                        loadedObject = assembly.CreateInstance(sInstanceName);
					if (null == loadedObject)
						return null;
			
					object[] sArrParams;
									
					
					if (this.m_sParameterType == ParameterType.Array)
					{
						sArrParams = new object[this.m_sParameterArray.Length];
						sArrParams = this.m_sParameterArray;
					}
					else
					{
						sArrParams = new string[1];
						sArrParams[0] = this.m_sParameters;
					}
					
					try
					{
						objReturn = loadedObject.GetType().InvokeMember(this.m_sFunctionName, flags, null, loadedObject, sArrParams, null, null, null);						
						break;
					}
					catch
					{
						return null;
					}					
				}
			}		

			return objReturn;
		}

        private string getBinFolderPath()
        {
            const string sBinFolder = "bin";
            string sRelativelyPath = RequestContext.GetRelativelyPath();  //获取相对路径
            string sAppPath = HttpContext.Current.Server.MapPath(sRelativelyPath + sBinFolder) + "\\";

            return sAppPath;
        }
    }
    
    ///<summary>
	///进行动态编译的.NET语言的种类
	/// </summary>
	public enum ScriptLanguageType
	{
		/// <summary>
		///		C#代码
		/// </summary>
		CSharpCode = 1,
		/// <summary>
		///		VB.NET代码
		/// </summary>
		VBCode = 2
	}

	/// <summary>
	///	进行动态编译的表达式的类型
	/// </summary>
	public enum ScriptExpressionType
	{
		/// <summary>
		///计算表达式
		/// </summary>
		FormulaCode = 1,

		///<summary>
		///脚本代码
		///</summary>
		ScriptCode = 2
	}

	/// <summary>
	///		导入组件的类型
	/// </summary>
	public enum ImportComponentType
	{
		/// <summary>
		///		COM+ DLL组件
		/// </summary>
		ComPlusDll = 1,
		/// <summary>
		///		.NET DLL组件
		/// </summary>
		DotNetDll = 2
	}

    /// <summary>
    /// 参数类型枚举
    /// </summary>
	public enum ParameterType
	{
        /// <summary>
        /// xml 类型
        /// </summary>
		Xml = 1,
        /// <summary>
        /// 值类型
        /// </summary>
		Text = 2,
        /// <summary>
        /// 数组类型
        /// </summary>
		Array = 3
	}

    /// <summary>
    /// 反射调用类型
    /// STATIC: 要反射调用的方法为静态方法
    /// INSTANCE: 要反射调用的方法为实例方法
    /// </summary>
    public enum InstanceType
    {
        /// <summary>
        /// 静态方法
        /// </summary>
        STATIC = 1,
        /// <summary>
        /// 实例方法
        /// </summary>
        INSTANCE = 2
    }
}
